package ru.startandroid.firstproj;

import java.io.FileWriter;
import java.io.IOException;


public class maze
{
    private int x, y, step = 2;
    public long time_gen_before, time_gen_after;
    private int[][] field;
    private int [][] matrix;
    private object exit_maze;
    maze()
    {
        x = 0; y = 0;
    }
    public object get()
    {
    	return new object(y, x);
    }
    public void set(int M, int N)
    {
        x = N;
        y = M;
        field = new int[y][x];
        matrix = new int[y][x];
    }
    protected void change (int i, int j, int q)
    {
        field[i][j] = q;
    }
    public int elem(int m, int n)
    {
        return field[m][n];
    }
    public object ex()
    {
        return exit_maze;
    }
        
    private boolean pbtp(int y1, int x1, int y2, int x2) //path between two point
    {
        for (int i = 0; i < y; i++)
            for (int j = 0; j < x; j++)
                if (field[i][j] == 0)
                    matrix[i][j] = 0;
                else
                    matrix[i][j] = 1;
        matrix[y1][x1] = 2;

        int coord_size = x*2;
        int[][] coord = new int[2][coord_size];
        /*     y 0 0 ...
               x 0 0 ...    */

        coord[0][0] = y1;
        coord[1][0] = x1;
        boolean path_exist = true;
        int yi, xi, it = 2;

        while ( matrix[y2][x2] == 1 && path_exist )
        {
            for (int j = 0, k = 0; j < coord_size && coord[0][j] != 0 ; j++)
            {
                yi = coord[0][j];
                xi = coord[1][j];
                if ( matrix[yi][xi] == it ) {

                    //up
                    if ( matrix[yi - 1][xi] == 1 ) {
                        matrix[yi - 1][xi] = it + 1;

                        while ( matrix [ coord[0][k] ][ coord[1][k] ] == it || matrix [ coord[0][k] ][ coord[1][k] ] == it + 1 )
                            k++;

                        coord[0][k] = yi - 1;
                        coord[1][k] = xi;

                        path_exist = true;
                    }

                    //down
                    if ( matrix[yi + 1][xi] == 1 ) {
                        matrix[yi + 1][xi] = it + 1;

                        while ( matrix [ coord[0][k] ][ coord[1][k] ] == it || matrix [ coord[0][k] ][ coord[1][k] ] == it + 1 )
                            k++;

                        coord[0][k] = yi + 1;
                        coord[1][k] = xi;

                        path_exist = true;
                    }

                    //left
                    if ( matrix[yi][xi - 1] == 1 ) {
                        matrix[yi][xi - 1] = it + 1;

                        while ( matrix [ coord[0][k] ][ coord[1][k] ] == it || matrix [ coord[0][k] ][ coord[1][k] ] == it + 1 )
                            k++;

                        coord[0][k] = yi;
                        coord[1][k] = xi - 1;

                        path_exist = true;
                    }

                    //right
                    if ( matrix[yi][xi + 1] == 1 ) {
                        matrix[yi][xi + 1] = it + 1;

                        while ( matrix [ coord[0][k] ][ coord[1][k] ] == it || matrix [ coord[0][k] ][ coord[1][k] ] == it + 1 )
                            k++;

                        coord[0][k] = yi;
                        coord[1][k] = xi + 1;

                        path_exist = true;
                    }

                }
                else
                    if ( it > matrix[ coord[0][0] ][ coord[1][0] ] )
                        path_exist = false;
            }
            it++;
        }
        return matrix[y2][x2] != 1;
    }
    private void change_line(char c, int numb)
    {
        int tmp;
        if ( c == 'v' )
    	{
    		for (int i = 2; i < y-2; i+=step)
    		{
    			tmp = field[i][numb];
    				field[i][numb] = 0;
    			if ( !pbtp(i-1, numb, i+1, numb) )
                    field[i][numb] = tmp;
    		}
    	}
    	if ( c == 'h' )
    	{
    		for (int j = 2; j < x-2; j+=step)
    		{
    			tmp = field[numb][j];
    				field[numb][j] = 0;
    			if ( !pbtp(numb, j-1, numb, j+1) )
                    field[numb][j] = tmp;
    		}
    	}
    }
    
    public void generate()
    {
        long startTime = System.currentTimeMillis();
        int last_string = y-2, prev_last_str = y-4;

        for (int i = 1; i < y-1; ++i)
        {
            for (int j = 1; j < x-1 && i != last_string; ++j)
            {
                if ( i % 2 != 0)
                {
                    if ( j % step != 0 )
                    {
                        if (field[i - 1][j] == 0)
                            field[i][j] = (j + 1) / 2;
                        else
                            field[i][j] = field[i-1][j];
                    }
                    else
                    {
                        if ( functions.rand_g(2) == 1 )
                        {
                            field[i][j] = field[i][j-1];
                            field[i][j+1] = field[i][j];
                            ++j;
                        }
                    }
                }
                else
                {
                    int k = 0;
                    for (int h = j; h < x-1; ++h)
                    {
                        if ( field[i-1][h] == 0 )
                            break;
                        ++k;
                    }
                    int p = k >> 1;

                    if (p == 0)
                        field[i][j] = field[i-1][j];
                    else {
                        boolean path = false;
                        for ( ; p > 0; --p)
                        {
                            if ( functions.rand_g(2) == 1 )
                            {
                                int w = functions.rand_g(k);
                                if ( w % 2 != 0 )
                                    ++w;
                                field[i][j+w] = field[i-1][j];
                                path = true;
                            }
                        }

                        if ( !path )
                        {
                            int w = functions.rand_g(k);
                            if ( w % 2 != 0 )
                                ++w;
                            field[i][j+w] = field[i-1][j];
                        }
                    }
                    j += k;
                }
            }
            field[i][x-1] = 0;

            if ( i == last_string )
            {
                for (int j = 0; j < x; ++j)
                {
                    field[last_string][j] = field[prev_last_str][j];
                    if (field[prev_last_str][j] == 0 && j > 0 && j < x-1)  
                        field[prev_last_str][j] = field[prev_last_str][j-1];
                }                
            }
        }

        time_gen_before = System.currentTimeMillis() - startTime;

        change_line('h', prev_last_str);
        change_line('v', x-2);

        time_gen_after = System.currentTimeMillis() - startTime - time_gen_before;

        int ex = functions.rand_g(2) + 1, u;
        switch (ex)
        {
            case 1:
                do {
                    u = functions.rand_g(4)+1;
                }
                while ( field[u][1] == 0 || field[u][x-2] == 0 );
                
                if ( field[u][1] != 0 )
                {
                	field[u][0] = 1;
                	exit_maze = new object(u, 0);
                }
                else
                {
                	field[u][x-1] = 1;
                	exit_maze = new object(u, x-1);
                }      
                
                break;
            case 2:
                do {
                    u = functions.rand_g(4)+1;
                }
                while (field[1][u] == 0 || field[y-2][u] == 0 );
                
                if ( field[1][u] != 0 )
                {
                	field[0][u] = 1;
                	exit_maze = new object(0, u);
                }
                else
                {
                	field[y-1][u] = 1; 
                	exit_maze = new object(y-1, u);
                }
                break;
        }
    }

    public void read()
    {

    }
    public void print(String p) throws IOException
    {
		String str = "";
    	FileWriter f = new FileWriter(p);
        for (int i = 0; i < y; i++)
        {
            for (int j = 0; j < x; j++)
                if (field[i][j] == 0)
                    str += "O";
                else
                    str += " ";
            str += "\n";
        }
        f.write(str);
        f.close();
    }

}
